﻿using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dotnet.Utils.Utility.Json
{
    public class JsonUtil
    {
        public static string DateTimeFormat = "yyyy'-'MM'-'dd";///'T'HH':'mm':'ss";//"yyyy-MM-dd HH:mm:ss";//
        public static string Encode(object o)
        {
            List<JsonConverter> converterList = new List<JsonConverter>();
            IsoDateTimeConverter dt = new IsoDateTimeConverter();
            dt.DateTimeFormat = DateTimeFormat;
            converterList.Add(dt);
            Int32Converter con = new Int32Converter();
            converterList.Add(con);

            //Newtonsoft.Json.Converters.
            // converterList.Add(new JSExtendItemConverter());

            //dt.DateTimeStyles = System.Globalization.DateTimeStyles.
            JsonSerializerSettings setting = new JsonSerializerSettings();
            setting.DefaultValueHandling = DefaultValueHandling.Include;
            setting.NullValueHandling = NullValueHandling.Include;
            setting.Converters = converterList;
            //return JsonConvert.SerializeObject(o, setting);//converterList.ToArray());//, new ListJsonConverter());
            return JsonConvert.SerializeObject(o, Formatting.None, setting);
        }
        /// <summary>
        /// 字典类型转化为json格式
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static string Encode2(Dictionary<string, string> o)
        {
            string result = "{";
            foreach (KeyValuePair<string, string> dic in o)
            {
                result += String.Format("\"{0}\":\"{1}\",", dic.Key, dic.Value);
            }
            result = result.Substring(0, result.Length - 1);
            return result + "}";
        }
        /// <summary>
        /// 字典类型转化为json格式
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static string Encode2(Dictionary<string, object> o)
        {
            string result = "{";
            foreach (KeyValuePair<string, object> dic in o)
            {
                result += String.Format("\"{0}\":{1},", dic.Key, Encode(dic.Value));
            }
            result = result.Substring(0, result.Length - 1);
            return result + "}";
        }
        public static T Decode<T>(string json)
        {
            return (T)Decode(json, typeof(T));
        }
        public static T DecodeFile<T>(string fileName)
        {
            if (File.Exists(fileName))
            {
                using (StreamReader reader = new StreamReader(fileName))
                {
                    string json = reader.ReadToEnd();
                    return (T)Decode(json, typeof(T));
                }
            }
            return default(T);
        }

        /// <summary>
        /// 非标准格式的{"Key":"Value"}键值对行JSON 
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static KeyValuePair<string, string>? DecodeKeyValue(string json)
        {
            KeyValuePair<string, string>? pair = null;
            JToken obj = JsonConvert.DeserializeObject(json) as JToken;
            if (obj.First is JProperty)
            {
                JProperty jp = obj.First as JProperty;
                pair = new KeyValuePair<string, string>(jp.Name, jp.Value.ToString());

            }

            return pair;
        }

        public static Dictionary<string, object> Decode2Dict(string json)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            JToken obj = JsonConvert.DeserializeObject(json) as JToken;
            JToken p = obj.First;
            while (p.Next != null)
            {
                JProperty jp = p as JProperty;
                if (jp != null)
                    dict.Add(jp.Name, jp.Value);
            }
            return dict;
        }
        public static object Decode(string json)
        {
            object o = JsonConvert.DeserializeObject(json);

            object v = toObject(o);
            return v;
        }
        /// <summary>
        /// Int32专用转换器
        /// </summary>
        class Int32Converter : JsonConverter
        {
            /// <summary>
            /// 当前类型是否使用当前转换器
            /// </summary>
            /// <param name="objectType"></param>
            /// <returns></returns>
            public override bool CanConvert(Type objectType)
            {
                bool canConvert = false;
                switch (objectType.FullName)
                {
                    //类型为Int32时使用该转换器
                    case "System.Int32":

                        canConvert = true;
                        break;

                }
                if (objectType.IsSubclassOf(typeof(System.Enum)))
                    canConvert = true;
                return canConvert;
            }
            /// <summary>
            /// 读取Json值
            /// </summary>
            /// <param name="reader"></param>
            /// <param name="objectType"></param>
            /// <param name="existingValue"></param>
            /// <param name="serializer"></param>
            /// <returns></returns>
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                return existingValue;
            }
            /// <summary>
            /// 写入Json字符串
            /// </summary>
            /// <param name="writer"></param>
            /// <param name="value"></param>
            /// <param name="serializer"></param>
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                //如果int值是不允许的值直接输出空字符串
                if (Convert.ToInt32(value) == NoneValue.NaInt)
                {
                    writer.WriteValue(string.Empty);
                }
                else
                {
                    writer.WriteValue(value);
                }

            }
        }
        class MyDateTimeConverter : IsoDateTimeConverter
        {
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                if (objectType == typeof(DateTime))
                {
                    string svalue = reader.Value.ToString();
                    if (string.IsNullOrEmpty(svalue))
                    {
                        return existingValue;
                    }
                    else if (svalue.Length == 19 && svalue[10] == 'T' && svalue[4] == '-' && svalue[13] == ':')
                    {
                        return System.Convert.ToDateTime(svalue);
                    }
                    else if (svalue.Length == 23 && svalue.Contains("."))
                    {
                        return System.Convert.ToDateTime(svalue);
                    }
                    else if (svalue.Contains("GMT"))
                    {
                        DateTime dt = DateTime.MinValue;
                        bool suc = DateTime.TryParse(svalue, out dt);
                        if (!suc)
                        {
                            dt = GMT2Local(svalue);
                        }
                        return dt;
                    }
                }
                return base.ReadJson(reader, objectType, existingValue, serializer);
            }
            /// <summary>   
            /// GMT时间转成本地时间   
            /// </summary>   
            /// <param name="gmt">字符串形式的GMT时间</param>   
            /// <returns></returns>   
            private DateTime GMT2Local(string gmt)
            {
                DateTime dt = DateTime.MinValue;
                try
                {
                    string pattern = "";
                    int index = gmt.ToUpper().IndexOf("GMT");
                    if (gmt.IndexOf("+0") != -1)
                    {
                        gmt = gmt.Replace("GMT", "");
                        pattern = "ddd MMM dd HH':'mm':'ss zzz yyyy";
                    }
                    if (gmt.ToUpper().IndexOf("GMT") != -1)
                    {
                        pattern = "ddd MMM dd HH':'mm':'ss 'GMT' zzz yyyy";
                    }
                    if (pattern != "")
                    {
                        dt = DateTime.ParseExact(gmt, pattern, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AdjustToUniversal);
                        dt = dt.ToLocalTime();
                    }
                    else
                    {
                        dt = Convert.ToDateTime(gmt);
                    }
                }
                finally
                {

                }
                return dt;
            }
            //public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            //{
            //    if ((DateTime)value == new DateTime(1, 1, 1))
            //    {
            //        writer.WriteNull();
            //    }
            //    else
            //    {
            //        base.WriteJson(writer, value, serializer);
            //    }
            //}
        }

        //class JSExtendItemConverter : JsonConverter
        //{

        //    public override bool CanConvert(Type objectType)
        //    {
        //        return (objectType.Equals(typeof(ExtendBusiItem)));
        //    }

        //    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        //    {
        //        return null;
        //    }

        //    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        //    {
        //        ExtendBusiItem item = value as ExtendBusiItem;
        //        if (item != null)
        //        {
        //            //if (item.IsDefTable)
        //            //{
        //                string strProperties = encode(item.ExtendProperties);
        //                writer.WriteRawValue(strProperties);
        //            //}
        //        }
        //    }

        //    private string encode(Dictionary<string, string> o)
        //    {
        //        string result = "{";
        //        foreach (KeyValuePair<string, string> dic in o)
        //        {
        //            result += String.Format("\"{0}\":\"{1}\",", dic.Key, dic.Value);
        //        }
        //        result = result.Substring(0, result.Length - 1);
        //        return result + "}";
        //    }
        //}

        public static object Decode(string json, Type type)
        {
            if (String.IsNullOrEmpty(json))
            {
                //加入判断，减少异常抛出
                if (type.FullName == "System.Int32")
                    return Int32.MinValue;
                else if (type.FullName == "System.Int16")
                    return Int16.MinValue;
                else if (type.FullName == "System.Int64")
                    return Int64.MinValue;
                else if (type.FullName == "System.DateTime")
                    return NoneValue.NaDateTime;
                else if (type.FullName == "System.Decimal")
                    return NoneValue.NaDecimal;
                return null;
            }
            JsonSerializerSettings setting = new JsonSerializerSettings();
            setting.DefaultValueHandling = DefaultValueHandling.Include;
            setting.NullValueHandling = NullValueHandling.Ignore;
            MyDateTimeConverter dt = new MyDateTimeConverter();
            dt.DateTimeFormat = DateTimeFormat;
            setting.Converters.Add(dt);
            setting.MissingMemberHandling = MissingMemberHandling.Ignore;
            try
            {
                return JsonConvert.DeserializeObject(json, type, setting);
            }
            catch
            {
                return null;

            }//, new ListJsonConverter());
        }
        private static object toObject(object o)
        {
            if (o == null) return null;

            if (o.GetType() == typeof(string))
            {
                //判断是否符合2010-09-02T10:00:00的格式
                string s = o.ToString();
                if (s.Length == 19 && s[10] == 'T' && s[4] == '-' && s[13] == ':')
                {
                    o = System.Convert.ToDateTime(o);
                }
            }
            else if (o is JObject)
            {
                JObject jo = o as JObject;

                Hashtable h = new Hashtable();

                foreach (KeyValuePair<string, JToken> entry in jo)
                {
                    h[entry.Key] = toObject(entry.Value);
                }

                o = h;
            }
            else if (o is IList)
            {

                ArrayList list = new ArrayList();
                list.AddRange((o as IList));
                int i = 0, l = list.Count;
                for (; i < l; i++)
                {
                    list[i] = toObject(list[i]);
                }
                o = list;

            }
            else if (typeof(JValue) == o.GetType())
            {
                JValue v = (JValue)o;
                o = toObject(v.Value);
            }
            else
            {
            }
            return o;
        }

    }
    /// <summary>
    /// 表单中出现的列表信息的JSON转换
    /// 因为表单中的值为字符串，不能直接转化，现在改为支持字符串的转换
    /// </summary>
    public class ListJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            if (objectType.IsGenericType)
            {
                return objectType.GetGenericTypeDefinition() == typeof(List<>).GetGenericTypeDefinition() ||
                    objectType.GetGenericTypeDefinition() == typeof(List<>).GetGenericTypeDefinition();
            }
            else
            {
                return false;// typeof(Lis).IsAssignableFrom(objectType);
            }
            // return false;
            //return typeof(IList<>).IsAssignableFrom(objectType); 
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            ///表单上提交过来的数据格式，就是文本类型的，需要重新解析
            if (reader.TokenType == JsonToken.String)
            {
                string sVal = "" + reader.Value;
                if (string.IsNullOrEmpty(sVal))
                {
                    return null;
                }
                else
                {
                    return JsonConvert.DeserializeObject(sVal, objectType);
                }
            }
            else if (reader.TokenType == JsonToken.StartArray)
            {
                Type eleType = objectType.GetGenericArguments()[0];
                IList objArray = Activator.CreateInstance(objectType) as IList;
                reader.Read();
                if (reader.TokenType == JsonToken.EndArray)
                {
                    return objArray;
                }
                while (reader.TokenType == JsonToken.StartObject)
                {
                    object objVal = serializer.Deserialize(reader, eleType);
                    objArray.Add(objVal);
                    reader.Read();
                }
                reader.Read();
                return objArray;
            }
            else
            {
                throw new Exception("参数错误，不能解析:" + objectType.Name);
            }
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            IList list = value as IList;
            writer.WriteStartArray();
            foreach (var item in list)
            {
                serializer.Serialize(writer, item);
            }
            writer.WriteEndArray();
        }
    }
}
